// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

#include "AbilitySystemComponent.h"
#include "LyraAttributeSet.h"
#include "NativeGameplayTags.h"

#include "LyraHealthSet.generated.h"

#define UE_API LYRAGAME_API

class UObject;
struct FFrame;

LYRAGAME_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(TAG_Gameplay_Damage); // 声明游戏玩法标签：伤害
LYRAGAME_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(TAG_Gameplay_DamageImmunity); // 声明游戏玩法标签：伤害免疫
LYRAGAME_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(TAG_Gameplay_DamageSelfDestruct); // 声明游戏玩法标签：自毁伤害
LYRAGAME_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(TAG_Gameplay_FellOutOfWorld); // 声明游戏玩法标签：掉出世界
LYRAGAME_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(TAG_Lyra_Damage_Message); // 声明游戏玩法标签：Lyra伤害消息

struct FGameplayEffectModCallbackData;

/**
 * ULyraHealthSet
 *
 *	定义承受伤害所需属性的类。
 *	属性示例包括：生命值、护盾和抗性。
 */
UCLASS(MinimalAPI, BlueprintType)
class ULyraHealthSet : public ULyraAttributeSet
{
	GENERATED_BODY()

public:

	UE_API ULyraHealthSet(); // 构造函数

	ATTRIBUTE_ACCESSORS(ULyraHealthSet, Health); // 为Health属性生成Get/Set函数
	ATTRIBUTE_ACCESSORS(ULyraHealthSet, MaxHealth); // 为MaxHealth属性生成Get/Set函数
	ATTRIBUTE_ACCESSORS(ULyraHealthSet, Healing); // 为Healing属性生成Get/Set函数
	ATTRIBUTE_ACCESSORS(ULyraHealthSet, Damage); // 为Damage属性生成Get/Set函数

	// 当生命值因伤害/治疗而改变时的委托，客户端可能缺少某些信息
	mutable FLyraAttributeEvent OnHealthChanged;

	// 当最大生命值改变时的委托
	mutable FLyraAttributeEvent OnMaxHealthChanged;

	// 当生命值属性达到零时广播的委托
	mutable FLyraAttributeEvent OnOutOfHealth;

protected:

	UFUNCTION()
	UE_API void OnRep_Health(const FGameplayAttributeData& OldValue); // Health属性复制回调函数

	UFUNCTION()
	UE_API void OnRep_MaxHealth(const FGameplayAttributeData& OldValue); // MaxHealth属性复制回调函数

	UE_API virtual bool PreGameplayEffectExecute(FGameplayEffectModCallbackData& Data) override; // 游戏效果执行前的处理
	UE_API virtual void PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data) override; // 游戏效果执行后的处理

	UE_API virtual void PreAttributeBaseChange(const FGameplayAttribute& Attribute, float& NewValue) const override; // 属性基础值改变前的处理
	UE_API virtual void PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue) override; // 属性当前值改变前的处理
	UE_API virtual void PostAttributeChange(const FGameplayAttribute& Attribute, float OldValue, float NewValue) override; // 属性改变后的处理

	UE_API void ClampAttribute(const FGameplayAttribute& Attribute, float& NewValue) const; // 限制属性值的辅助函数

private:

	// 当前生命值属性。生命值将受最大生命值属性限制。生命值对修改器隐藏，因此只有执行可以修改它。
	UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_Health, Category = "Lyra|Health", Meta = (HideFromModifiers, AllowPrivateAccess = true))
	FGameplayAttributeData Health;

	// 当前最大生命值属性。最大生命值是一个属性，因为游戏效果可以修改它。
	UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_MaxHealth, Category = "Lyra|Health", Meta = (AllowPrivateAccess = true))
	FGameplayAttributeData MaxHealth;

	// 用于跟踪生命值何时达到0。
	bool bOutOfHealth;

	// 存储任何更改前的生命值
	float MaxHealthBeforeAttributeChange; // 属性改变前的最大生命值
	float HealthBeforeAttributeChange; // 属性改变前的生命值

	// -------------------------------------------------------------------
	//	元属性（请将非“状态性”属性放在下面）
	// -------------------------------------------------------------------

	// 传入的治疗量。这直接映射到+Health
	UPROPERTY(BlueprintReadOnly, Category="Lyra|Health", Meta=(AllowPrivateAccess=true))
	FGameplayAttributeData Healing;

	// 传入的伤害量。这直接映射到-Health
	UPROPERTY(BlueprintReadOnly, Category="Lyra|Health", Meta=(HideFromModifiers, AllowPrivateAccess=true))
	FGameplayAttributeData Damage;
};

#undef UE_API // 取消定义UE_API宏